package com.sunda.spmsweb.wmscontroller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmsweb.feign.IFeignService;
import com.sunda.spmsweb.util.JWTUtil;
import com.sunda.spmswms.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.UUID;

import static com.sunda.spmscommon.Constans.*;

/**
 * <p>
 * SAP交货单表头 前端控制器
 * </p>
 *
 * @author Wayne
 * @since 2021-03-19
 */
@RestController
@RequestMapping("/sapDeliveryNote")
@Api(tags = "SAP DN交货单", description = "SAP DN交货单接口")
public class SapDeliveryNoteController {

    @Autowired
    ISapDeliveryNoteService iSapDeliveryNoteService;

    @Autowired
    ISapDeliveryNoteLogService iSapDeliveryNoteLogService;

    @Autowired
    IFeignService iFeignService;

    @Autowired
    IShelfOnTaskService iShelfOnTaskService;

    @Autowired
    IShelfOnTaskDtlService iShelfOnTaskDtlService;

    @Autowired
    ISapBoxNoteWithdraw iSapBoxNoteWithdraw;

    @Autowired
    ISapDeliveryNoteWithdrawMService iISapDeliveryNoteWithdrawMService;

    @RequestMapping("/getSapDeliverNote")
    @ApiOperation(value = "获取SAP DN单表头信息", notes = "获取SAP DN单表头信息,搜索条件，spmsMark 为空则忽略条件；" +
            "spmsMark = M 则只查贸易货；spmsMark = X 则只查备件货； \n" +
            "20210707————查询条件中交货单号不为空，且在spms系统查不到结果时，会实时从sap请求该交货单数据。" +
            "请求成功则将该数据写入数据库，返回该数据查询结果；请求不成功，显示SAP返回错误信息；\n" +
            "单据状态控制：0-待到货；1-已到货；2-下发到PDA；3-收货中；4-待上架；5-上架中；6-已验收待上传SAP；" +
            "7-提交SAP失败；8-提交SAP完成；9-回撤重新入库；10-部分完成；11-关闭；\n" +
            "{\n" +
            "\t\"werks\": \"CN01\",\n" +
            "\t\"whsLocationCode\": \"1061\",\n" +
            "\t\"deliveryNoteSap\": \"1180066360\",\n" +
            "\t\"deliveryNoteSrm\": \"\",\n" +
            "\t\"sapVoucherNumber\": \"\",\n" +
            "\t\"deliveryType\": \"\",\n" +
            "\t\"plaEndDate\": \"20210414\",\n" +
            "\t\"plaStartDate\": \"20210301\",\n" +
            "\t\"spmsStatus\": \"3\",\n" +
            "\t\"spmsMark\": \"X\",\n" +
            "\t\"supplierCode\":\"\",\n" +
            "\t\"pageNo\": \"1\",\n" +
            "\t\"pageSize\": \"20\"\n" +
            "}", httpMethod = "POST")
    public ResponseResult getSapDeliverNote(@RequestBody JSONObject searchCriteria) {

        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            Map<String, Object> mapInfo = iSapDeliveryNoteService.getSapDeliveryNote(userId, searchCriteria);
            if (mapInfo.containsKey("sapReturnedData")){
                /** 查询条件中交货单号不为空，且在spms系统查不到结果时，会实时从sap请求该交货单数据。
                 * 请求成功则将该数据写入数据库，返回该数据查询结果；
                 * 请求不成功，显示SAP返回错误信息；
                 * */
                return ResponseResult.error()
                        .add("dataToSap", JSONObject.parseObject(mapInfo.get("dataToSap").toString()))
                        .add("sapReturnedData", JSONObject.parseObject(mapInfo.get("sapReturnedData").toString()));
            }
            return ResponseResult.success().add("sapDN", mapInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("获取SAP DN失败");
        }
    }

    @RequestMapping("/closeOrOpenSapDeliveryNote")
    @ApiOperation(value = "关闭或开启交货单", notes = "关闭或开启交货单\n" +
            "单据状态控制：0-待到货；1-已到货；2-下发到PDA；3-收货中；4-待上架；5-上架中；6-已验收待上传SAP；" +
            "7-提交SAP失败；8-提交SAP完成；9-回撤重新入库；10-部分完成；11-关闭；\n" +
            "关闭/开启自管仓交货单，关闭单据 operateType = 0；开启单据 operateType = 1；\n" +
            "", httpMethod = "POST")
    public ResponseResult closeOrOpenSapDeliveryNote(@RequestParam String deliveryNoteSap, @RequestParam String operateType) {
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return iSapDeliveryNoteService.closeOrOpenSapDeliveryNote(deliveryNoteSap, operateType, userId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("交货单关闭或开启错误").add("error", e.getMessage());
        }
    }

    @RequestMapping("/getOrderDataBySapDn")
    @ApiOperation(value = "根据DN单号获取详情数据", notes = "根据DN单号获取详情数据，deliveryNoteSap = 1180066360", httpMethod = "GET")
    public ResponseResult getOrderDataBySapDn(@RequestParam String deliveryNoteSap) {
        try {
            return ResponseResult.success().add("deliveryData", iSapDeliveryNoteService.getOrderReceiveDatabySapDN(deliveryNoteSap));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("获取SAP DN失败").add("error", e.getMessage());
        }
    }


    @RequestMapping("/updateSapDeliveryNote")
    @ApiOperation(value = "更新交货单表头信息", notes = "更新交货单表头信息，交货单号：1180066259 \n" +
            "1. deliveryNoteSap, SAP DN单号，必须 \n" +
            "2. spmsStatus, 表单当前状态，必须 \n" +
            "3. remarks, 收货单备注，可选 \n" +
            "4. documentDate, 凭证日期-开始处理日期,可选 \n" +
            "5. postingDate, 过账日期-提交SAP日期,可选 \n" +
            "6. mobileType, 移动类型,可选 \n" +
            "7. userId", httpMethod = "POST")
    public ResponseResult updateSapDeliveryNote(@RequestParam String deliveryNoteSap,
                                                @RequestParam String spmsStatus,
                                                @RequestParam(defaultValue = "") String remarks,
                                                @RequestParam(defaultValue = "") String documentDate,
                                                @RequestParam(defaultValue = "") String postingDate,
                                                @RequestParam(defaultValue = "") String mobileType,
                                                @RequestParam(defaultValue = "") String userId,
                                                @RequestParam(defaultValue = "") String operateUser
    ) {
        try {
            userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return iSapDeliveryNoteService.updateSapDeliveryNote(deliveryNoteSap, spmsStatus, remarks, documentDate, postingDate, mobileType, userId, operateUser);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("更新交货单失败").add("error", e.getMessage());
        }
    }

    @RequestMapping("/updateSapDeliveryNoteDtl")
    @ApiOperation(value = "更新交货单行项目、库存信息(贸易货)", notes = "更新交货单行项目、库存信息；\n" +
            "1.更新交货单对应行项目 实收数量、状态 字段；\n" +
            "2.实收数量 更新完成后，更新 储位-物料-数量 关系数据；储位存在对应物料，则更新数量、可用数量；储位不存在对应物料，则新建 储位-物料-数量 数据；\n" +
            "3.增加储位操作日志。\n" +
            "20210624 接口变更，收货详情中新增字段 actualQtySales 销售单位实收数量；\n" +
            "{\n" +
            "\t\"SapDeliveryNoteDtl\": [{\n" +
            "\t\t\"deliveryNoteSap\": \"\",\n" +
            "\t\t\"deliveryNoteSapItem\": 10,\n" +
            "\t\t\"materialNo\": \"130010159\",\n" +
            "\t\t\"deliveryQty\": 2,\n" +
            "\t\t\"receivedQty\": 2,\n" +
            "\t\t\"actualQtySales\": 2,\n" +
            "\t\t\"storageUuidList\": [{\n" +
            "\t\t\t\"storageUuid\": \"64eaf8633b3e4b8aa276970f2e31785b\",\n" +
            "\t\t\t\"qty\": 1\n" +
            "\t\t}]\n" +
            "\t}]\n" +
            "}", httpMethod = "POST")
    public ResponseResult updateSapDeliveryNoteDtl(@RequestBody JSONObject doc) {
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        try {
            return iSapDeliveryNoteService.updateSapDeliveryNoteDtl(doc, userId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("更新交货单明细失败");
        }
    }

    /**
     * 20210415 注释以下接口，备件收货不会一步完成，接口弃用
     */
//    @RequestMapping("/updateSapBoxNote")
//    @ApiOperation(value = "更新箱码行项目、库存信息(备件货)", notes = "更新交货单箱码行项目、库存信息；\n" +
//            "1.更新交货单对应箱码信息 实收数量、状态 字段；\n" +
//            "2.实收数量 更新完成后，更新 储位-箱码-数量 关系数据；储位存在对应箱码，则更新数量；储位不存在对应箱码，则新建 储位-箱码-数量 数据。\n" +
//            "{\n" +
//            "\t\"sapBoxNotes\": [{\n" +
//            "\t\t\"boxNote\": \"ZX-10218300001-0202\",\n" +
//            "\t\t\"boxQtyReceived\": 1,\n" +
//            "\t\t\"storageUuid\": \"b95946ac1dab42b79ade3438acb0b53h\",\n" +
//            "\t\t\"qty\": 1,\n" +
//            "\t\t\"itemStatus\": \"1\"\n" +
//            "\t}]\n" +
//            "}", httpMethod = "POST")
//    public  ResponseResult updateSapBoxNote(@RequestBody JSONObject doc){
//        try {
//            return iSapDeliveryNoteService.updateSapBoxNote(doc);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return ResponseResult.error("更新交货单明细失败");
//        }
//    }

    /**
     *
     * @param deliveryNoteSap
     * @param status
     * @return
     */
    @RequestMapping("/getDNByDN")
    @ApiOperation(value = "根据DN从SAP实时更新DN详细信息", notes = "根据DN单号获取DN信息，从SAP同步：交货单表头、交货单表头供应商、交货单明细、" +
            "包装单号表、箱码信息表、箱码明细表 六张表数据；示例交货单号：1180066276。SPMS_STATUS 字段值为空值 和 0 以外的值时，前端需做控制禁止刷新。"
            , httpMethod = "GET")
    public synchronized ResponseResult getDNByDN(@RequestParam String deliveryNoteSap,
                                    @RequestParam(defaultValue = "") String status) {
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        String json = "{\n" +
                "    \"REQUEST\": {\n" +
                "        \"ESB_ATTRS\": {\n" +
                "            \"App_ID\": \"SPMS\", \n" +
                "            \"Application_ID\": \"00020000000002\", \n" +
                "            \"Transaction_ID\": " + "\"" + UUID.randomUUID() + "\"" +
                "        }, \n" +
                "        \"REQUEST_DATA\": {\n" +
                "            \"Head\": {\n" +
                "                \"iVbeln\": " + "\"" + deliveryNoteSap + "\",\n" +
                "                \"iStatus\": " + "\"" + status + "\"\n" +
                "            }, \n" +
                "            \"Operation\": \"Z_SPMS_GETDN_REST\", \n" +
                "            \"Type\": \"GETDN\"\n" +
                "        }\n" +
                "    }\n" +
                "}";
        try {
            String message = iFeignService.sendRestToSap(JSONObject.parseObject(json));
            if (StringUtils.isEmpty(message)) {
                return ResponseResult.error();
            }
            System.out.println("\n\n" + message.toString() + "\n\n");
            JSONObject doc = JSONObject.parseObject(message).getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            /** 更新交货单表头、供应商、行项目等信息 */
            if (doc.containsKey("O_TYPE") && "S".equals(doc.getString("O_TYPE"))){
                /** 从SAP获取交货单数据成功，备件货写入数据前先删掉该交货单所有关联数据 */
                ResponseResult deleteResult = iSapDeliveryNoteService.deleteDnRelateDoc(deliveryNoteSap);
                if (deleteResult.getCode() != SUCCESS){
                    return deleteResult;
                }
                iSapDeliveryNoteService.insertSapDeliveryNote(doc);
                iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_DELIVERY_NOTE,
                        JSONObject.parseObject(message).toJSONString(), JSONObject.parseObject(json).toJSONString());
                return ResponseResult.success("从SAP获取交货单信息成功").add("responseMsg", doc).add("requestMsg", json).add("deliveryData", iSapDeliveryNoteService.getOrderReceiveDatabySapDN(deliveryNoteSap));
            }
            iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_DELIVERY_NOTE_ERROR,
                    JSONObject.parseObject(message).toJSONString(), JSONObject.parseObject(json).toJSONString());
            return ResponseResult.error("从SAP获取交货单信息错误").add("responseMsg", doc).add("requestMsg", json);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error();
        }
    }

    @PostMapping("/getSpDeliveryNoteTask")
    @ApiOperation(value = "获取当前人名下交货单信息(备件货)", notes = "获取当前人名下交货单信息(备件货)\n" +
            "{\n" +
            "\t\"deliveryNoteSap\": \"1180066364\",\n" +
            "\t\"plaEndDate\": \"20210414\",\n" +
            "\t\"plaStartDate\": \"20210301\",\n" +
            "\t\"spmsStatus\": \"3\",\n" +
            "\t\"pageNo\": \"1\",\n" +
            "\t\"pageSize\": \"20\"\n" +
            "}")
    public ResponseResult getSpDeliveryNoteTask(@RequestBody JSONObject doc) {
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return ResponseResult.success().add("sapDN", iSapDeliveryNoteService.getSpDeliveryNoteTask(userId, doc));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("获取交货单信息失败");
        }
    }

    @PostMapping("/updateSapDeliveryNoteTask")
    @ApiOperation(value = "PDA更新交货单状态——仅PDA", notes = "PDA更新交货单状态，待到货-0状态更新为 下发到PDA-2，返回更新后的交货单信息；\n" +
            "如果交货单不存在或者状态为 空 或 0，则实时向SAP请求一次该交货单最新数据，再返回更新结果数据；\n" +
            "更新之前，检查该交货单存在、为备件收货、有明细行数据、有包装单号、有箱码、有箱码明细，如果信息不完善则返回错误信息；\n" +
            "{\n" +
            "\t\"deliveryNoteSap\": \"1180066364\",\n" +
            "\t\"currentStatus\": \"0\",\n" +
            "\t\"targetStatus\": \"2\"\n" +
            "}")
    public ResponseResult updateSapDeliveryNoteTask(@RequestBody JSONObject doc) {
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return iSapDeliveryNoteService.updateSapDeliveryNoteTask(doc, userId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("更新交货单信息失败");
        }
    }

    @PostMapping("/getDnDataToSap")
    @ApiOperation(value = "交货单提交SAP(贸易货，备件货)", notes = "根据交货单号查询交货单表头及行项目信息提交SAP\n" +
            "1.交货单号示例：deliveryNoteSap = 1180066369；过账日期用户可输入，示例 postingDate = 20210330；\n" +
            "2.首先将 过账日期字段 写入数据库；\n" +
            "3.提交前单据状态是 6 —— 待提交SAP 或 7 —— 提交SAP失败\n" +
            "4.\"O_TYPE\": \"S\" ———— 提交SAP成功，单据完成；更新交货单状态为 8 —— 提交SAP完成；\n" +
            "5.\"O_TYPE\": \"E\" ———— 提交SAP不成功，单据未完成，更新单据状态为 7 —— 提交SAP失败； 显示错误信息给用户；（上游单据锁住，提交失败、过账日期错误、网络错误等原因会导致提交失败。）" +
            "6.以上各步骤均要写入用户操作日志信息。")
    public synchronized ResponseResult getDnDataToSap(String deliveryNoteSap, String postingDate, String remarks, String operateUser) {
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        try {
            /** 先将过账日期字段更新到交货单，再获取将要提交到SAP的交货单表头及明细信息。同时记录交货单 提交SAP 或 重提SAP 日志信息。 */
            Map<String, Object> getDnDataToSap = iSapDeliveryNoteService.getDnDataToSap(deliveryNoteSap, postingDate, userId, remarks, operateUser);
            if (getDnDataToSap != null) {
                /** 提交SAP获取返回信息 */
                String message = iFeignService.sendRestToSap(JSONObject.parseObject(getDnDataToSap.toString()));
                if (StringUtils.isEmpty(message)) {
                    iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(deliveryNoteSap, userId, UPDATE_SAP_DELIVERY_NOTE7);
                    return ResponseResult.error("获取SAP返回信息出错");
                }
                JSONObject RETURN_DATA = JSONObject.parseObject(message).getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (RETURN_DATA.containsKey("TYPE") && "TIP".equals(RETURN_DATA.getString("TYPE").toUpperCase())) {
                    return ResponseResult.error("ESB连接错误");
                }
                if ("S".equals(RETURN_DATA.getString("O_TYPE"))) {
                    /** SPMS 每次只会提交一个交货单到SAP，返回的信息结构体中的JSONArray —— IT_MSG 也会只有一条数据；sapVoucherNumber - SAP物料凭证号； sapVoucherYear - SAP凭证年度 */
                    String sapVoucherNumber = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MBLNR");
                    String sapVoucherYear = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MJAHR");
                    iSapDeliveryNoteService.updateSapDeliveryNoteStatus(deliveryNoteSap, "8", sapVoucherNumber, sapVoucherYear);
                    iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_SAP_DELIVERY_NOTE8,
                            JSONObject.parseObject(message).toJSONString(), getDnDataToSap.toString());
                    return ResponseResult.success(RETURN_DATA.getString("O_MSTXT")).add("sapReturnMsg", RETURN_DATA.getString("O_MSTXT"))
                            .add("sapReturnTotalMsg", JSONObject.parseObject(message)).add("sendSapMsg", getDnDataToSap)
                            .add("sapDN", iSapDeliveryNoteService.getSapDnByDn(deliveryNoteSap));
                }
                /** 提交SAP失败，1.更新请购单状态为 7-提交SAP失败； */
                iSapDeliveryNoteService.updateSapDeliveryNoteStatus(deliveryNoteSap, "7", "", "");
                iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_SAP_DELIVERY_NOTE7,
                        JSONObject.parseObject(message).toJSONString(), getDnDataToSap.toString());
                return ResponseResult.error(RETURN_DATA.getString("O_MSTXT")).add("sapReturnMsg", RETURN_DATA.getString("O_MSTXT"))
                        .add("sapReturnTotalMsg", JSONObject.parseObject(message)).add("sendSapMsg", getDnDataToSap);
            } else {
                return ResponseResult.error("提交SAP时获取交货单信息出错，请刷新重试");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("交货单提交SAP错误").add("error", e.getMessage());
        }
    }

    @PostMapping("/checkSapDeliveryNote")
    @ApiOperation(value = "来货确认收货(备件货)", notes = "来货确认收货(备件货)\n" +
            "pdaSn PDA设备号；documentDate 验收用户当前日期，格式：yyyy-MM-dd，即为凭证日期；\n" +
            "1.操作前单据状态 spmsStatus 需为 2 —— 下发到PDA；传入参数单据目标 spmsStatus 状态 6 - 已验收待上传SAP；\n" +
            "2.更新交货单表头 SAP_DELIVERY_NOTE 状态为 6 —— 已验收待上传SAP；\n" +
            "3.更新箱码信息表 SAP_BOX_NOTE 实收箱数量；\n" +
            "4.将对应箱码写入仓库库存信息表 WHS_INVENTORY_INFO ；\n" +
            "5.记录仓库库存变更日志记录；" +
            "6.更新箱码明细表 SAP_BOX_NOTE_DTL 箱码箱实收数量、物料实收数量；\n" +
            "7.记录交货单操作日志信息 SAP_DELIVERY_NOTE_LOG；\n" +
            "8.生成上架任务 SHELF_ON_TASK ；\n" +
            "9.生成上架任务明细 SHELF_ON_TASK_DTL ；\n" +
            "10.记录上架任务日志信息 SAP_DELIVERY_NOTE_LOG ;" +
            "{\n" +
            "\t\"pdaSn\": \"pda20210412\",\n" +
            "\t\"documentDate\": \"2020-04-12\",\n" +
            "\t\"sapDeliveryNote\": {\n" +
            "\t\t\"deliveryNoteSap\": \"1180066380\",\n" +
            "\t\t\"mobileType\": \"101\",\n" +
            "\t\t\"spmsStatus\": \"6\"\n" +
            "\t},\n" +
            "\t\"sapBoxNote\": [{\n" +
            "\t\t\"boxNote\": \"ZX-10215800021-0202\",\n" +
            "\t\t\"boxQtyReceived\": 1,\n" +
            "\t\t\"remarks\": \"说明信息\"\n" +
            "\t}]\n" +
            "}")
    public ResponseResult checkSapDeliveryNote(@RequestBody JSONObject doc) {
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return iSapDeliveryNoteService.checkSapDeliveryNote(userId, doc);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("更新交货单信息失败");
        }
    }


    @PostMapping("/sapDeliveryNoteRecX")
    @ApiOperation(value = "一步确认收货,上架(备件货)", notes = "一步确认收货，上架(备件货)\n" +
            "pdaSn PDA设备号；documentDate 验收用户当前日期，格式：yyyy-MM-dd，即为凭证日期；\n" +
            "1.调用备件来货确认验证接口 /sapDeliveryNote/checkSapDeliveryNote；\n" +
            "2.调用备件上架接口完成上架，说细入参照备件上架接口；\n" +
            "{\n" +
            "  \"documentDate\": \"2021-04-16\",\n" +
            "  \"pdaSn\": \"WebClient\",\n" +
            "  \"sapBoxNote\": [\n" +
            "    {\n" +
            "      \"boxNote\": \"ZX-10215800021-0202\",\n" +
            "      \"boxQtyReceived\": 1,\n" +
            "      \"storageUuid\": \"b95946ac1dab42b79ade3438acb0b53a\",\n" +
            "      \"remarks\":\"Your remarks\"\n" +
            "    }\n" +
            "  ],\n" +
            "  \"sapDeliveryNote\": {\n" +
            "    \"deliveryNoteSap\": \"1180066380\",\n" +
            "    \"mobileType\": \"101\",\n" +
            "    \"operateUser\": \"operate User\",\n" +
            "    \"remarks\": \"remarks for this sapn DN\"\n" +
            "    \"spmsStatus\": \"6\"\n" +
            "  }\n" +
            "}")
    public ResponseResult sapDeliveryNoteRecX(@RequestBody JSONObject doc) {
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        return iSapDeliveryNoteService.sapDeliveryNoteRecX(doc, userId);
    }

    @PostMapping("/sapDeliveryNoteRecM")
    @ApiOperation(value = "一步确认收货,上架(贸易货)", notes = "一步确认收货,上架(贸易货) \n" +
            "20210624 接口变更，收货详情中新增字段 actualQtySales 销售单位实收数量；\n" +
            "{\n" +
            "  \"SapDeliveryNote\": {\n" +
            "    \"deliveryNoteSap\": \"1180066308\",\n" +
            "    \"spmsStatus\": \"6\",\n" +
            "    \"documentDate\": \"20210417\",\n" +
            "    \"postingDate\": \"20210417\",\n" +
            "    \"mobileType\": \"101\",\n" +
            "    \"userId\": \"999904\",\n" +
            "    \"operateUser\": \"qwe\",\n" +
            "    \"remarks\": \"remarks for this sapn DN\"\n" +
            "  },\n" +
            "  \"SapDeliveryNoteDtl\": [\n" +
            "    {\n" +
            "      \"deliveryNoteSap\": \"1180066308\",\n" +
            "      \"deliveryNoteSapItem\": 10,\n" +
            "      \"materialNo\": \"130010159\",\n" +
            "      \"deliveryQty\": 200,\n" +
            "      \"receivedQty\": 200,\n" +
            "      \"actualQtySales\": 200,\n" +
            "      \"storageUuidList\": [\n" +
            "        {\n" +
            "          \"storageUuid\": \"64eaf8633b3e4b8aa276970f2e31785b\",\n" +
            "          \"qty\": 100\n" +
            "        },\n" +
            "        {\n" +
            "          \"storageUuid\": \"64eaf8633b3e4b8aa276970f2e31785c\",\n" +
            "          \"qty\": 100\n" +
            "        }\n" +
            "      ]\n" +
            "    }\n" +
            "  ]\n" +
            "}")
    public ResponseResult sapDeliveryNoteRecM(@RequestBody JSONObject jsonObject) {
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        return iSapDeliveryNoteService.sapDeliveryNoteRecM(jsonObject, userId);
    }

    @PostMapping("/withdrawSapDeliverNoteM")
    @ApiOperation(value = "贸易货冲销接口", notes = "贸易货冲销接口 \n" +
            "{\n" +
            "  \"deliveryNoteSap\":\"1180066249\",\n" +
            "  \"createDate\":\"20210422\" ,\n" +
            "  \"mobileType\":\"102\",\n" +
            "  \"cancelPostingDate\":\"2021-09-09\",\n" +
            "  \"cancelRemark\":\"remarks\"" +
            "}")
    public ResponseResult withdrawSapDeliverNoteM(@RequestBody JSONObject jsonObject) {
        String deliveryNoteSap = jsonObject.getString("deliveryNoteSap");
        String createDate = jsonObject.getString("createDate");
        String mobileType = jsonObject.getString("mobileType");
        String cancelPostingDate = jsonObject.getString("cancelPostingDate");
        String cancelRemark = jsonObject.getString("cancelRemark");
        if (StringUtils.isEmpty(deliveryNoteSap) || StringUtils.isEmpty(createDate) || StringUtils.isEmpty(mobileType)
                || StringUtils.isEmpty(cancelPostingDate) || "Invalid date".equals(cancelPostingDate)) {
            return ResponseResult.error("deliveryNoteSap,mobileType and createDate are mandatory required");
        }
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        // 库存检查，以确定是否可以冲销
        ResponseResult isWithdrawable = iISapDeliveryNoteWithdrawMService.isWithdrawableM(deliveryNoteSap, userId, createDate);
        if (isWithdrawable.getCode() == 200) {
            String spmsStatus = isWithdrawable.getData().get("spmsStatus") == null ? null : isWithdrawable.getData().get("spmsStatus").toString();
            switch (spmsStatus) {
                case "3":
                case "6":
                case "7":
                    // 状态为2，6，7时未同步到sap， 直接在库内冲销
                    if (iISapDeliveryNoteWithdrawMService.withdrawSapDeliveryNote(deliveryNoteSap, userId, createDate, "", mobileType).getCode() == 200) {
                        JSONObject sapDNO = new JSONObject();
                        sapDNO.put("deliveryNoteSap", deliveryNoteSap);
                        return ResponseResult.success().add("sapDN", iSapDeliveryNoteService.getSpDeliveryNoteTask(userId, sapDNO));
                    }
                case "8":
                case "11":
                    // 状态为8，11时已同步到sap， 需要先调用SAP冲消接口，如果成功，再库内撤销
                    String sapVoucherNumber = isWithdrawable.getData().get("sapVoucherNumber") == null ? null : isWithdrawable.getData().get("sapVoucherNumber").toString();
                    String sapVoucherYear = isWithdrawable.getData().get("sapVoucherYear") == null ? null : isWithdrawable.getData().get("sapVoucherYear").toString();
                    if (StringUtils.isEmpty(sapVoucherNumber) || StringUtils.isEmpty(sapVoucherYear)) {
                        return ResponseResult.error("sapVoucherNumber or sapVoucherYear is missed");
                    }
                    ResponseResult zSpmsCancelRes = zSpmsCancel(sapVoucherNumber, sapVoucherYear, deliveryNoteSap, cancelPostingDate, cancelRemark);
                    if (zSpmsCancelRes.getCode() != 200) {
                        // 调用sap接口失败
                        return zSpmsCancelRes;
                    }
                    Object zSpmsData = zSpmsCancelRes.getData();
                    String MBLNR = ((Map) zSpmsData).get("MBLNR").toString();
                    if (iISapDeliveryNoteWithdrawMService.withdrawSapDeliveryNote(deliveryNoteSap, userId, createDate, MBLNR, mobileType).add("zSpmsSapRes", zSpmsData).getCode() == 200) {
                        JSONObject sapDNO = new JSONObject();
                        sapDNO.put("deliveryNoteSap", deliveryNoteSap);
                        return ResponseResult.success().add("sapDN", iSapDeliveryNoteService.getSpDeliveryNoteTask(userId, sapDNO));
                    }
                default:
                    return ResponseResult.error("SPMS Staus invalidate, spmsStatus: " + spmsStatus);
            }
        }
        return isWithdrawable;
    }

    @PostMapping("/withdrawSapBoxNote")
    @ApiOperation(value = "备件货冲销接口", notes = "备件货冲销接口 \n" +
            "{\n" +
            "  \"deliveryNoteSap\":\"1180066249\",\n" +
            "  \"createDate\":\"20210422\" ,\n" +
            "  \"mobileType\":\"102\",\n" +
            "  \"cancelPostingDate\":\"2021-09-09\",\n" +
            "  \"cancelRemark\":\"remarks\"" +
            "}")
    public ResponseResult withdrawSapBoxNote(@RequestBody JSONObject jsonObject) {
        String deliveryNoteSap = jsonObject.getString("deliveryNoteSap");
        String createDate = jsonObject.getString("createDate");
        String mobileType = jsonObject.getString("mobileType");
        String cancelPostingDate = jsonObject.getString("cancelPostingDate");
        String cancelRemark = jsonObject.getString("cancelRemark");
        if (StringUtils.isEmpty(deliveryNoteSap) || StringUtils.isEmpty(createDate) || StringUtils.isEmpty(mobileType) ||
                StringUtils.isEmpty(cancelPostingDate) || "Invalid date".equals(cancelPostingDate)) {
            return ResponseResult.error("deliveryNoteSap,mobileType and createDate are mandatory required");
        }
        String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
        // 库存检查，以确定是否可以冲销
        ResponseResult isWithdrawable = iSapBoxNoteWithdraw.isWithdrawableX(deliveryNoteSap, userId, createDate);
        if (isWithdrawable.getCode() == 200) {
            String spmsStatus = isWithdrawable.getData().get("spmsStatus") == null ? null : isWithdrawable.getData().get("spmsStatus").toString();
            switch (spmsStatus) {
                case "2":
                case "6":
                case "7":
                    // 状态为2，6，7时未同步到sap， 直接在库内冲销
                    if (iSapBoxNoteWithdraw.withdrawSapBoxNote(deliveryNoteSap, userId, createDate, "", mobileType).getCode() == 200) {
                        iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(deliveryNoteSap, userId, "撤销成功");
                        JSONObject sapDNO = new JSONObject();
                        sapDNO.put("deliveryNoteSap", deliveryNoteSap);
                        return ResponseResult.success().add("sapDN", iSapDeliveryNoteService.getSpDeliveryNoteTask(userId, sapDNO));
                    }
                case "8":
                case "11":
                    // 状态为8，11时已同步到sap， 需要先调用SAP冲消接口，如果成功，再库内撤销
                    String sapVoucherNumber = isWithdrawable.getData().get("sapVoucherNumber") == null ? null : isWithdrawable.getData().get("sapVoucherNumber").toString();
                    String sapVoucherYear = isWithdrawable.getData().get("sapVoucherYear") == null ? null : isWithdrawable.getData().get("sapVoucherYear").toString();
                    if (StringUtils.isEmpty(sapVoucherNumber) || StringUtils.isEmpty(sapVoucherYear)) {
                        return ResponseResult.error("sapVoucherNumber or sapVoucherYear is missed");
                    }
                    ResponseResult zSpmsCancelRes = zSpmsCancel(sapVoucherNumber, sapVoucherYear, deliveryNoteSap, cancelPostingDate, cancelRemark);
                    if (zSpmsCancelRes.getCode() != 200) {
                        // 调用sap接口失败
                        return zSpmsCancelRes;
                    }
                    Object zSpmsData = zSpmsCancelRes.getData();
                    String MBLNR = ((Map) zSpmsData).get("MBLNR").toString();
                    if (iSapBoxNoteWithdraw.withdrawSapBoxNote(deliveryNoteSap, userId, createDate, MBLNR, mobileType).add("zSpmsSapRes", zSpmsData).getCode() == 200) {
                        JSONObject sapDNO = new JSONObject();
                        sapDNO.put("deliveryNoteSap", deliveryNoteSap);
                        return ResponseResult.success().add("sapDN", iSapDeliveryNoteService.getSpDeliveryNoteTask(userId, sapDNO));
                    }
                default:
                    return ResponseResult.error("SPMS Staus invalidate, spmsStatus: " + spmsStatus);
            }
        }
        return isWithdrawable;
    }

    @RequestMapping("/zSpmsCancel")
    @ApiOperation(value = "根据SAP物料凭证和年份冲销", notes = "SPMS系统在做MIGO收货动作的时候，需要做反冲处理，" +
            "预防收错货或者是收货数量与填错信息，此时需要整单DN全部冲销，在SAP系统可以直接MBST冲销，SPMS系统不支持做部分冲销。\n" +
            "sapVoucherNumber SAP物料凭证，必输； sapVoucherYear 凭证年份，必输；"
            , httpMethod = "GET")
    public ResponseResult zSpmsCancel(@RequestParam String sapVoucherNumber,
                                      @RequestParam String sapVoucherYear,
                                      @RequestParam String deliveryNoteSap,
                                      String cancelPostingDate, String cancelRemark) {
        cancelPostingDate = cancelPostingDate.replaceAll("-", "");
        String json = "{\n" +
                "\t\"REQUEST\": {\n" +
                "\t\t\"ESB_ATTRS\": {\n" +
                "\t\t\t\"App_ID\": \"SPMS\",\n" +
                "\t\t\t\"Application_ID\": \"00020000000002\",\n" +
                "\t\t\t\"Transaction_ID\": " + "\"" + UUID.randomUUID() + "\"" +
                "\t\t},\n" +
                "\t\t\"REQUEST_DATA\": {\n" +
                "\t\t\t\"Head\": {\n" +
                "\t\t\t\t\"iMblnr\": " + "\"" + sapVoucherNumber + "\",\n" +
                "\t\t\t\t\"iMjahr\": " + "\"" + sapVoucherYear + "\",\n" +
                "\t\t\t\t\"iBudat\": " + "\"" + cancelPostingDate + "\"\n" +
                "\t\t\t},\n" +
                "\t\t\t\"Operation\": \"Z_SPMS_CANCEL\",\n" +
                "\t\t\t\"Type\": \"SPMS_CANCEL\"\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}";
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            String message = iFeignService.sendRestToSap(JSONObject.parseObject(json));
            if (StringUtils.isEmpty(message)) {
                return ResponseResult.error("No response from SAP");
            }
            System.out.println("\n\n" + message.toString() + "\n\n");
            JSONObject RETURN_DATA = JSONObject.parseObject(message).getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            String O_TYPE = RETURN_DATA.getString("O_TYPE");
            String cancelSapVoucherNumber = RETURN_DATA.getString("0_MBLNR");
            if (O_TYPE.equals("S")) {
                iSapDeliveryNoteService.updateCancelSapDeliveryNote(deliveryNoteSap, cancelPostingDate, cancelSapVoucherNumber, cancelRemark);
                iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_DELIVERY_NOTE_CANCEL,
                        JSONObject.parseObject(message).toJSONString(), JSONObject.parseObject(json).toJSONString());
                return ResponseResult.success()
                        .add("responseMsg", JSONObject.parseObject(message))
                        .add("requestMsg", json)
                        .add("MBLNR", RETURN_DATA.getString("0_MBLNR"));
            } else {
                iSapDeliveryNoteLogService.insertSapRequestRecord(deliveryNoteSap, userId, UPDATE_DELIVERY_NOTE_CANCEL_ERROR,
                        JSONObject.parseObject(message).toJSONString(), JSONObject.parseObject(json).toJSONString());
                return ResponseResult.error().add("responseMsg", JSONObject.parseObject(message)).add("requestMsg", json);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when invoking SAP interface");
        }
    }

    @RequestMapping("/getSapDnLog")
    @ApiOperation(value = "获取交货单关联日志", notes = "获取交货单关联日志\n" +
            "获取交货单关联日志，入参 交货单号：deliveryNoteSap = 1180066185",
            httpMethod = "POST")
    public ResponseResult getSapDnLog(String deliveryNoteSap) {
        return ResponseResult.success().add("deliveryNoteSapLog", iSapDeliveryNoteLogService.getDocumentLogs(deliveryNoteSap));
    }

    @PostMapping("/lockSapDeliveryNote")
    @ApiOperation(value = "交货单执行通知SAP上锁",notes = "交货单执行通知SAP上锁" +
            "deliveryNoteSap = 1180066503")
    public ResponseResult lockSapDeliveryNote(String deliveryNoteSap){
        try {
            String userId = JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
            return iSapDeliveryNoteService.lockSapDeliveryNote(deliveryNoteSap, userId);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error("交货单上锁出错");
        }
    }
}
